///////////////////////////////////////////////////////////////////////////////
// $Id: reg_file.v 1 2009-10-08 18:23:02Z root $
//
// Module: reg_file.v
// Project: CPCI (PCI Control FPGA)
// Description: Register file for access via PCI
//
//
// Change history: 8/18/04 - Implemented DWORD0 (Revision/Version ID)
//                 10/29/04 - Made the RESET signal last longer than
//                 a single clock
//                 01/08/05 - dma_rd_mac is now an input as round-robin
//                 lookup is used
//                 01/13/05 - split dma_intr into read and write sigs
//
///////////////////////////////////////////////////////////////////////////////

module reg_file(
            // PCI Signals
            input [`PCI_ADDR_WIDTH-1:0] pci_addr,      // PCI Address
            input          reg_hit,       // Register hit
            input          reg_we,        // Write Enable
            input [`PCI_BE_WIDTH-1:0]   pci_be,        // Byte Enable
            input [`PCI_DATA_WIDTH-1:0] pci_data,      // Data being written from the PCI interface
            input          pci_data_vld,  // Data on pci_data is valid
            
            output reg [`PCI_DATA_WIDTH-1:0]  reg_data,  // Data being read by the PCI interface
            output         reg_vld,       // Data on reg_data is valid

            output reg     reg_reset,     // Reset signal generated by
                                          // writing to the reset register

            output reg [`PCI_DATA_WIDTH-1:0] prog_data,  // Reprogramming data
            output reg     prog_data_vld, // Reprogramming data valid?
            output reg     prog_reset,    // Reset the programming process

            output         intr_req,      // Signal an interrupt

            input          cnet_hit,      // CNET hit flag
            input          cnet_we,       // CNET write enable flag
            // Reprogramming flags
	    input          empty,         // CNET reprogram FIFO is empty (1)  
            input          prog_init,     // In init state
            input          prog_done,     // Programming is done
            input          cnet_reprog,   // Is reprogramming in progess

            // DMA signals
            output reg [31:0] dma_rd_addr, // Address when performing reads
            output reg [31:0] dma_wr_addr, // Address when performing writes

            input [3:0]    dma_rd_mac,    // Which MAC was data read from
            output reg [3:0] dma_wr_mac,  // Which MAC to write data to

            input [31:0]   dma_rd_size,   // Packet size when performing reads
            output reg [31:0] dma_wr_size, // Packet size when performing writes

            output reg     dma_rd_owner, // Who owns read buffer (1 = CPCI)
            output reg     dma_wr_owner, // Who owns write buffer (1 = CPCI)

            input          dma_rd_done,   // The current read is done
            input          dma_wr_done,   // The current write is done

            input          dma_in_progress, // A DMA transfer is in progress
            
            output reg [31:0] dma_time,   // Number of clocks before a DMA transfer times out

            output reg [15:0] dma_retries, // Number of retries before a DMA transfer times out

            // CNET register access
            output reg [31:0] cnet_rd_time,  // Number of clocks before a CNET read timeout occurs

            // Board identification
            input          cpci_jmpr,     // Jumper on board
            input [3:0]    cpci_id,       // Rotary switch on board

            // Error flags
            input          prog_overflow, // Overflow in buffer during prog
            input          prog_error,    // Prog error
            input          dma_buf_overflow, // Overflow in buffer during DMA (CNET->CPCI)
            input          dma_rd_size_err, // DMA Read size is invalid
            input          dma_wr_size_err, // DMA Write size is invalid
            input          dma_rd_addr_err, // DMA Read address is invalid
            input          dma_wr_addr_err, // DMA Write address is invalid
            input          dma_rd_mac_err, // No data is available to read from the requested MAC
            input          dma_wr_mac_err, // No space is available to write to the requested MAC
            input          dma_timeout,   // Indicates a timeout has occured
            input          dma_retry_expire, // DMA retry counter has expired
            input          dma_fatal_err,  // DMA fatal error
            input          cnet_rd_timeout, // Indicated a timeout has occured
            input          cnet_err,      // Error flag from the CNET

            // Interrupt flags
            input          dma_rd_intr,   // DMA read operation has completed
            input          dma_wr_intr,   // DMA write operation has completed
            input          phy_intr,      // Interrupt request from the PHY

            // Are any packets available for DMA transfer
            input [15:0]   dma_pkt_avail,


            // CNET Clock Select
            output reg     cnet_clk_sel,

            // LED control
            output reg     cpci_led,      // LED on/off

	    // clock checker module
	    input  [31:0]   n_clk_count,   // counts network clk (sysclk) ticks in 10th second.
	    output reg [31:0]   clk_chk_p_max, // Max value when counting the PCI clock.
	    output reg [31:0]   clk_chk_n_exp, // Expected value of nclock when PCI counter reaches max value.
		
            // CNET reset
            output         try_cnet_reset, // Try to reset the CNET

            // 
            output reg     host_is_le,    // Host is little endian?

            input          pci_reset,
            input          clk
         );


// ==================================================================
// Local
// ==================================================================

wire reset;

reg reg_hit_d1;
reg reg_we_d1;

reg cnet_hit_d1;
reg cnet_we_d1;

reg [`PCI_ADDR_WIDTH-1:0] pci_addr_d1;

// ==================================================================
// Implement id word
// ==================================================================

wire [`PCI_DATA_WIDTH - 1:0] id_data;

assign id_data = {`CPCI_REVISION_ID, `CPCI_VERSION_ID};


// ==================================================================
// Implement board id word
// ==================================================================

wire [`PCI_DATA_WIDTH - 1:0] board_id_data;

assign board_id_data = {20'b0, cpci_id, 7'b0, cpci_jmpr};


// ==================================================================
// Implement control word
// ==================================================================

wire [`PCI_DATA_WIDTH - 1:0] ctrl_data;

assign ctrl_data = {15'b0, host_is_le, 8'b0, 7'b0, cpci_led};

// This register is used to introduce a pause. This is some future
// future proofing in case the PCI clock is ever run at 66 MHz.
reg [3:0] cnet_reset;

always @(posedge clk)
begin
   if (reset) begin
      cpci_led <= 1'b0;
      cnet_reset <= 4'b0000;
      host_is_le <= 1'b1;
   end
   else if (reg_we && pci_data_vld && pci_addr[11:2] == `CPCI_CTRL) begin
      cpci_led <= pci_data[0];
      cnet_reset[0] <= pci_data[8];
      host_is_le <= pci_data[16];
   end
   else begin
      cnet_reset <= {cnet_reset[2:0], 1'b0};
   end
end

assign try_cnet_reset = |(cnet_reset);


// ==================================================================
// Implement reset word
// ==================================================================

// This register is used to introduce a pause. This is some future
// future proofing in case the PCI clock is ever run at 66 MHz.
reg reset_pause;

always @(posedge clk)
begin
   if (pci_reset) begin
      reg_reset <= 1'b0;
      reset_pause <= 1'b0;
   end
   else if (reg_we && pci_data_vld && pci_addr[11:2] == `CPCI_RESET) begin
      reg_reset <= pci_data[0];
      reset_pause <= pci_data[0];
   end
   else if (reset_pause) begin
      reg_reset <= 1'b1;
      reset_pause <= 1'b0;
   end
   else begin
      reg_reset <= 1'b0;
      reset_pause <= 1'b0;
   end
end


// ==================================================================
// Implement error word
// ==================================================================

reg [`PCI_DATA_WIDTH - 1:0] error_status;
wire [`PCI_DATA_WIDTH - 1:0] error_flags;

always @(posedge clk)
begin
   if (reset)
      error_status <= 1'b0;
   else if (reg_we && pci_data_vld && pci_addr[11:2] == `CPCI_ERROR)
      error_status <= pci_data;
   else if (reg_hit_d1 && !reg_hit && !reg_we_d1 &&
          pci_addr[11:2] == `CPCI_ERROR)
      error_status <= error_flags;
   else
      error_status <= error_status | error_flags;
end

assign error_flags = {
            // 31:24
            6'b0,
            cnet_rd_timeout,
            cnet_err,

            // 23:16
            6'b0,
            prog_overflow,
            prog_error,

            // 15:8
            5'b0,
            dma_timeout,
            dma_retry_expire,
            dma_buf_overflow,

            // 7:0
            1'b0,
            dma_rd_size_err,
            dma_wr_size_err,
            dma_rd_addr_err,
            dma_wr_addr_err,
            dma_rd_mac_err,
            dma_wr_mac_err,
            dma_fatal_err
   };


// ==================================================================
// Implement dummy word
// ==================================================================

reg [`PCI_DATA_WIDTH - 1:0] test_data;

always @(posedge clk)
begin
   if (reset)
      test_data <= 'h0;
   else if (reg_we && pci_data_vld && pci_addr[11:2] == `CPCI_DUMMY) begin
      test_data[7:0] <= pci_be[0] ? pci_data[7:0] : test_data[7:0];
      test_data[15:8] <= pci_be[1] ? pci_data[15:8] : test_data[15:8];
      test_data[23:16] <= pci_be[2] ? pci_data[23:16] : test_data[23:16];
      test_data[31:24] <= pci_be[3] ? pci_data[31:24] : test_data[31:24];
   end
end


// ==================================================================
// Implement interrupt mask word
// ==================================================================

reg [`PCI_DATA_WIDTH - 1:0] interrupt_mask;

always @(posedge clk)
begin
   if (reset)
      interrupt_mask <= 'hffff_ffff;  // 1 = interrupt is masked (not enabled)
   else if (reg_we && pci_data_vld && pci_addr[11:2] == `CPCI_INTERRUPT_MASK)
      interrupt_mask <= pci_data;
end


// ==================================================================
// Implement interrupt flags
// ==================================================================

reg [`PCI_DATA_WIDTH - 1:0] interrupt_flags;
wire [`PCI_DATA_WIDTH - 1:0] new_interrupt_flags;
wire pkt_avail;
reg pkt_avail_d1;
wire pkt_avail_intr_req;
reg dma_in_progress_d1;

reg [`PCI_DATA_WIDTH - 1:0] rd_interrupt_flags;

always @(posedge clk)
begin
   if (reset)
      interrupt_flags <= 'h0;
   else if (reg_we && pci_data_vld && pci_addr[11:2] == `CPCI_INTERRUPT_STATUS)
      /* A write is taking place */
      interrupt_flags <= pci_data | new_interrupt_flags;
   else if (reg_hit_d1 && !reg_hit && !reg_we_d1 &&
          pci_addr_d1[11:2] == `CPCI_INTERRUPT_STATUS)
      /* A read has just finished */
      interrupt_flags <= rd_interrupt_flags | new_interrupt_flags;
   else if (reg_hit && !reg_we &&
          pci_addr[11:2] == `CPCI_INTERRUPT_STATUS)
      /* A read is taking place */
      interrupt_flags <= interrupt_flags;
   else
      interrupt_flags <= interrupt_flags | new_interrupt_flags;
end

always @(posedge clk)
begin
   if (reset)
      rd_interrupt_flags <= 'h0;
   else if (reg_hit && !reg_we &&
          pci_addr[11:2] == `CPCI_INTERRUPT_STATUS)
      rd_interrupt_flags <= rd_interrupt_flags | new_interrupt_flags;
   else
      rd_interrupt_flags <= 'h0;
end

// Note: mask off any signals coming from the CNET if prog_done is not
// asserted
assign new_interrupt_flags = {
            dma_rd_intr,
            dma_wr_intr,
            phy_intr & prog_done,
            20'b0,
            pkt_avail_intr_req & prog_done,
            2'b0,
            cnet_err & prog_done,
            cnet_rd_timeout,
            prog_overflow | prog_error,
            dma_timeout | dma_retry_expire,
            (dma_buf_overflow & prog_done) | 
            dma_rd_size_err | dma_wr_size_err | 
            dma_rd_addr_err | dma_wr_addr_err | 
            dma_rd_mac_err | dma_wr_mac_err,
            dma_fatal_err
   };

// The ugliness below is to generate an interrupt request only when one of
// the dma_pkt_avail flags transitions high or when one is already high
// and a dma is completed.
always @(posedge clk)
begin
   if (reset) 
   begin
      pkt_avail_d1 <= 1'b0;
      dma_in_progress_d1 <= 1'b0;
   end
   else
   begin
      pkt_avail_d1 <= pkt_avail;
      dma_in_progress_d1 <= dma_in_progress;
   end
end

assign pkt_avail = |(dma_pkt_avail);

assign pkt_avail_intr_req = pkt_avail & ~dma_in_progress &
            (~pkt_avail_d1 | dma_in_progress_d1);


// ==================================================================
// Implement CNET_clk_sel word
// ==================================================================

always @(posedge clk)
begin
   if (reset)
      cnet_clk_sel <= 'h1;
   else if (reg_we && pci_data_vld && pci_addr[11:2] == `CPCI_CNET_CLK_SEL) begin
      cnet_clk_sel <= pci_data[0];
   end
end


// ==================================================================
// Implement CNET programming data word
// ==================================================================

always @(posedge clk)
begin
   if (reset) begin
      prog_data <= 'h0;
      prog_data_vld <= 1'b0;
   end
   else if (reg_we && pci_data_vld && pci_addr[11:2] == `CPCI_REPROG_DATA) begin
      prog_data <= pci_data;
      prog_data_vld <= 1'b1;
   end
   else
      prog_data_vld <= 1'b0;
end


// ==================================================================
// Implement CNET programming status word
// ==================================================================

wire [`PCI_DATA_WIDTH - 1 : 0] prog_status;

assign prog_status = {8'b0, 7'b0, prog_init, 7'b0, prog_done, 6'b0, empty, cnet_reprog};


// ==================================================================
// Implement CNET programming control word
// ==================================================================

always @(posedge clk)
begin
   if (reset)
      prog_reset <= 1'b0;
   else if (reg_we && pci_data_vld && pci_addr[11:2] == `CPCI_REPROG_CTRL)
      prog_reset <= pci_data[0];
   else
      prog_reset <= 1'b0;
end


// ==================================================================
// Implement DMA Ingress Address (relative to driver)
// ==================================================================

always @(posedge clk)
begin
   if (reset)
      dma_rd_addr <= 'h0;
   else if (reg_we && pci_data_vld && pci_addr[11:2] == `CPCI_DMA_ADDR_I)
      dma_rd_addr <= pci_data;
end


// ==================================================================
// Implement DMA Egress Address (relative to driver)
// ==================================================================

always @(posedge clk)
begin
   if (reset)
      dma_wr_addr <= 'h0;
   else if (reg_we && pci_data_vld && pci_addr[11:2] == `CPCI_DMA_ADDR_E)
      dma_wr_addr <= pci_data;
end


// ==================================================================
// Implement DMA Ingress Size (relative to driver)
// ==================================================================

reg [`PCI_DATA_WIDTH - 1 : 0] dma_rd_size_q;

always @(posedge clk)
begin
   if (reset)
      dma_rd_size_q <= 'h0;
   else if (dma_rd_done)
      dma_rd_size_q <= dma_rd_size;
end


// ==================================================================
// Implement DMA Egress Size (relative to driver)
// ==================================================================

always @(posedge clk)
begin
   if (reset)
      dma_wr_size <= 'h0;
   else if (reg_we && pci_data_vld && pci_addr[11:2] == `CPCI_DMA_SIZE_E)
      dma_wr_size <= pci_data;
end


// ==================================================================
// Implement DMA Ingress Ctrl (relative to driver)
// ==================================================================

reg [3:0] dma_rd_mac_latched;
wire [`PCI_DATA_WIDTH - 1 : 0] dma_rd_ctrl;

always @(posedge clk)
begin
   if (reset) begin
      dma_rd_mac_latched <= 'h0;
      dma_rd_owner <= 1'b0;
   end
   else if (reg_we && pci_data_vld && pci_addr[11:2] == `CPCI_DMA_CTRL_I) begin
      dma_rd_mac_latched <= pci_data[9:8];
      dma_rd_owner <= pci_data[0];
   end
   else if (dma_rd_done) begin
      dma_rd_mac_latched  <= dma_rd_mac;
      dma_rd_owner <= 1'b0;
   end
end

assign dma_rd_ctrl = {20'b0, dma_rd_mac_latched , 7'b0, dma_rd_owner};


// ==================================================================
// Implement DMA Egress Ctrl (relative to driver)
// ==================================================================

wire [`PCI_DATA_WIDTH - 1 : 0] dma_wr_ctrl;

always @(posedge clk)
begin
   if (reset) begin
      dma_wr_mac <= 'h0;
      dma_wr_owner <= 1'b0;
   end
   else if (reg_we && pci_data_vld && pci_addr[11:2] == `CPCI_DMA_CTRL_E) begin
      dma_wr_mac <= pci_data[11:8];
      dma_wr_owner <= pci_data[0];
   end
   else if (dma_wr_done) begin
      dma_wr_owner <= 1'b0;
   end
end

assign dma_wr_ctrl = {20'b0, dma_wr_mac, 7'b0, dma_wr_owner};


// ==================================================================
// Implement DMA Transfer time
// ==================================================================

always @(posedge clk)
begin
   if (reset) 
      dma_time <= `CPCI_DMA_XFER_TIME_DEFAULT;
   else if (reg_we && pci_data_vld && pci_addr[11:2] == `CPCI_DMA_XFER_TIME)
      dma_time <= pci_data;
end


// ==================================================================
// Implement DMA max retry limiter
// ==================================================================

always @(posedge clk)
begin
   if (reset) 
      dma_retries <= `CPCI_DMA_RETRIES_DEFAULT;
   else if (reg_we && pci_data_vld && pci_addr[11:2] == `CPCI_DMA_RETRIES)
      dma_retries <= pci_data[15:0];
end


// ==================================================================
// Implement CNET Read time
// ==================================================================

always @(posedge clk)
begin
   if (reset) 
      cnet_rd_time <= `CPCI_CNET_READ_TIME_DEFAULT;
   else if (reg_we && pci_data_vld && pci_addr[11:2] == `CPCI_CNET_READ_TIME)
      cnet_rd_time <= pci_data;
end


// ==================================================================
// Implement DMA Ingress packet count (relative to CPCI)
// ==================================================================

reg [`PCI_DATA_WIDTH - 1:0] ingress_pkt_cnt;

always @(posedge clk)
begin
   if (reset || 
         reg_hit_d1 && !reg_hit && !reg_we_d1 &&
         pci_addr[11:2] == `CPCI_DMA_INGRESS_PKT_CNT)
      ingress_pkt_cnt <= 'h0;
   else if (reg_we && pci_data_vld && pci_addr[11:2] == `CPCI_DMA_INGRESS_PKT_CNT)
      ingress_pkt_cnt <= pci_data;
   else if (dma_wr_done)
      ingress_pkt_cnt <= ingress_pkt_cnt + 'h1;
end


// ==================================================================
// Implement DMA Egress packet count (relative to CPCI)
// ==================================================================

reg [`PCI_DATA_WIDTH - 1:0] egress_pkt_cnt;

always @(posedge clk)
begin
   if (reset || 
         reg_hit_d1 && !reg_hit && !reg_we_d1 &&
         pci_addr[11:2] == `CPCI_DMA_EGRESS_PKT_CNT)
      egress_pkt_cnt <= 'h0;
   else if (reg_we && pci_data_vld && pci_addr[11:2] == `CPCI_DMA_EGRESS_PKT_CNT)
      egress_pkt_cnt <= pci_data;
   else if (dma_rd_done)
      egress_pkt_cnt <= egress_pkt_cnt + 'h1;
end


// ==================================================================
// Implement CPCI register read count
// ==================================================================

reg [`PCI_DATA_WIDTH - 1:0] cpci_reg_rd_cnt;

always @(posedge clk)
begin
   if (reset || 
         reg_hit_d1 && !reg_hit && !reg_we_d1 &&
         pci_addr[11:2] == `CPCI_CPCI_REG_READ_CNT)
      cpci_reg_rd_cnt <= 'h0;
   else if (reg_we && pci_data_vld && pci_addr[11:2] == `CPCI_CPCI_REG_READ_CNT)
      cpci_reg_rd_cnt <= pci_data;
   else if (reg_hit_d1 && !reg_hit && !reg_we_d1)
      cpci_reg_rd_cnt <= cpci_reg_rd_cnt + 'h1;
end


// ==================================================================
// Implement CPCI register write count
// ==================================================================

reg [`PCI_DATA_WIDTH - 1:0] cpci_reg_wr_cnt;

always @(posedge clk)
begin
   if (reset || 
         reg_hit_d1 && !reg_hit && !reg_we_d1 &&
         pci_addr[11:2] == `CPCI_CPCI_REG_WRITE_CNT)
      cpci_reg_wr_cnt <= 'h0;
   else if (reg_we && pci_data_vld && pci_addr[11:2] == `CPCI_CPCI_REG_WRITE_CNT)
      cpci_reg_wr_cnt <= pci_data;
   else if (reg_hit_d1 && !reg_hit && reg_we_d1)
      cpci_reg_wr_cnt <= cpci_reg_wr_cnt + 'h1;
end


// ==================================================================
// Implement CNET register read count
// ==================================================================

reg [`PCI_DATA_WIDTH - 1:0] cnet_reg_rd_cnt;

always @(posedge clk)
begin
   if (reset || 
         reg_hit_d1 && !reg_hit && !reg_we_d1 &&
         pci_addr[11:2] == `CPCI_CNET_REG_READ_CNT)
      cnet_reg_rd_cnt <= 'h0;
   else if (reg_we && pci_data_vld && pci_addr[11:2] == `CPCI_CNET_REG_READ_CNT)
      cnet_reg_rd_cnt <= pci_data;
   else if (cnet_hit_d1 && !cnet_hit && !cnet_we_d1)
      cnet_reg_rd_cnt <= cnet_reg_rd_cnt + 'h1;
end


// ==================================================================
// Implement CNET register write count
// ==================================================================

reg [`PCI_DATA_WIDTH - 1:0] cnet_reg_wr_cnt;

always @(posedge clk)
begin
   if (reset || 
         reg_hit_d1 && !reg_hit && !reg_we_d1 &&
         pci_addr[11:2] == `CPCI_CNET_REG_WRITE_CNT)
      cnet_reg_wr_cnt <= 'h0;
   else if (reg_we && pci_data_vld && pci_addr[11:2] == `CPCI_CNET_REG_WRITE_CNT)
      cnet_reg_wr_cnt <= pci_data;
   else if (cnet_hit_d1 && !cnet_hit && cnet_we_d1)
      cnet_reg_wr_cnt <= cnet_reg_wr_cnt + 'h1;
end

// ==================================================================
// Implement PCI CLK free running counter.
// - used to calculate the true PCI clock frequency.
// ==================================================================

reg [`PCI_DATA_WIDTH - 1:0] cnet_pci_clk_cnt;

always @(posedge clk)
begin
   if (reset) 
     cnet_pci_clk_cnt <= 'h0;
   else if (reg_we && pci_data_vld && pci_addr[11:2] == `CPCI_PCI_CLK_CNT)
     cnet_pci_clk_cnt <= pci_data;
   else 
     cnet_pci_clk_cnt <= cnet_pci_clk_cnt + 'h1;
end

// ==================================================================
// Implement p_max and n_exp registers which are used by the
// clock_check module to verify the clock frequencies.
// ==================================================================

always @(posedge clk)
begin
   if (reset) begin
     clk_chk_p_max <= 'h0;
     clk_chk_n_exp <= 'h0;
   end
   else begin 
      if (reg_we && pci_data_vld && pci_addr[11:2] == `CPCI_CLOCK_CHECK_P_MAX)
	clk_chk_p_max <= pci_data;
      else 
	if (reg_we && pci_data_vld && pci_addr[11:2] == `CPCI_CLOCK_CHECK_N_EXP)
	  clk_chk_n_exp <= pci_data;
   end 
end 
   
// ==================================================================
// Implement CPCI soft reset counter - counts how often the software
// does a soft reset on the CPCI.
// ==================================================================

reg [`PCI_DATA_WIDTH - 1:0] cpci_reset_cnt;

always @(posedge clk)
  // DO NOT CLEAR ON RESET!!!!!!
  if (reg_we && pci_data_vld && pci_addr[11:2] == `CPCI_CPCI_RESET_CNT)
    cpci_reset_cnt <= pci_data;
  else if (reg_we && pci_data_vld && pci_addr[11:2] == `CPCI_RESET) begin
     cpci_reset_cnt <= cpci_reset_cnt + 1;
  end 

    
// ==================================================================
// Read MUX
// ==================================================================

always @*
begin : outputmux
   case (pci_addr[11:2])
      `CPCI_ID      : reg_data = id_data;
      `CPCI_BOARD_ID: reg_data = board_id_data;
      `CPCI_CTRL    : reg_data = ctrl_data;
      `CPCI_RESET   : reg_data = 'h0;
      `CPCI_ERROR   : reg_data = error_status;
      `CPCI_DUMMY   : reg_data = test_data;

      `CPCI_INTERRUPT_MASK   : reg_data = interrupt_mask;
      `CPCI_INTERRUPT_STATUS : reg_data = interrupt_flags;

      `CPCI_CNET_CLK_SEL  : reg_data = cnet_clk_sel;

      `CPCI_REPROG_DATA   : reg_data = 'h0;
      `CPCI_REPROG_STATUS : reg_data = prog_status;
      `CPCI_REPROG_CTRL   : reg_data = 'h0;

      `CPCI_DMA_ADDR_I : reg_data = dma_rd_addr;
      `CPCI_DMA_ADDR_E : reg_data = dma_wr_addr;
      `CPCI_DMA_SIZE_I : reg_data = dma_rd_size_q;
      `CPCI_DMA_SIZE_E : reg_data = dma_wr_size;
      `CPCI_DMA_CTRL_I : reg_data = dma_rd_ctrl;
      `CPCI_DMA_CTRL_E : reg_data = dma_wr_ctrl;
      
      `CPCI_DMA_XFER_TIME    : reg_data = dma_time;
      `CPCI_DMA_RETRIES      : reg_data = dma_retries;
      `CPCI_CNET_READ_TIME   : reg_data = cnet_rd_time;
      
      `CPCI_DMA_INGRESS_PKT_CNT : reg_data = ingress_pkt_cnt;
      `CPCI_DMA_EGRESS_PKT_CNT  : reg_data = egress_pkt_cnt;
      `CPCI_CPCI_REG_READ_CNT   : reg_data = cpci_reg_rd_cnt;
      `CPCI_CPCI_REG_WRITE_CNT  : reg_data = cpci_reg_wr_cnt;
      `CPCI_CNET_REG_READ_CNT   : reg_data = cnet_reg_rd_cnt;
      `CPCI_CNET_REG_WRITE_CNT  : reg_data = cnet_reg_wr_cnt;

      `CPCI_CLOCK_CHECK_N_CLK : reg_data = n_clk_count;
      `CPCI_CLOCK_CHECK_P_MAX : reg_data = clk_chk_p_max;
      `CPCI_CLOCK_CHECK_N_EXP : reg_data = clk_chk_n_exp;
      `CPCI_PCI_CLK_CNT       : reg_data = cnet_pci_clk_cnt;
      `CPCI_CPCI_RESET_CNT    : reg_data = cpci_reset_cnt;

      default           : reg_data = 32'h dead_beef;
   endcase
end


// ==================================================================
// Misc signal generation
// ==================================================================

assign reg_vld = !reg_we;
assign reset = pci_reset | reg_reset;
assign intr_req = |(interrupt_flags & ~interrupt_mask);

always @(posedge clk)
begin
   reg_hit_d1 <= reg_hit;
   reg_we_d1 <= reg_we;

   cnet_hit_d1 <= cnet_hit;
   cnet_we_d1 <= cnet_we;

   pci_addr_d1 <= pci_addr;
end

endmodule // reg_file

/* vim:set shiftwidth=3 softtabstop=3 expandtab: */
